package com.sinog.biz.schedule;

import com.sinog.biz.BizApplication;
import com.sinog.biz.config.RedisConfig;
import com.sinog.biz.mapper.havexml.SystemCodeMapper;
import com.sinog.biz.util.CodeUrlUtils;
import com.sinog.core.domain.SystemCode;
import com.sinog.core.model.SystemCodeVo;
import com.sinog.core.util.CollectionUtils;
import com.sinog.core.util.JsonUtil;
import com.sinog.core.utilbean.Constants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import redis.clients.jedis.Jedis;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @desc 定时任务：行政区划全国同步 每天晚23点55推 每天凌晨1点55拉
 * @author lzq
 * @date 2021-09-20 00:02
 */
@Slf4j
@Component
@Configuration
@ConditionalOnProperty(name = "gkzx.azbj.zd.open", havingValue = "true")
public class DictionarySchedule {

    private JdbcTemplate bujiJdbcTemplate;
    @Autowired
    private SystemCodeMapper systemCodeMapper;
    @Autowired
    private RedisConfig redisConfig;

    /**
     * 省市区县下拉全国同步(向部级数据库推送数据)
     * 实现步骤
     * 1.创建定时任务，凌晨1:25开始执行定时任务
     * 2.各个省级系统负责查找本省-(省市区县)code编码以及机构名称
     * 3.将本省级机构编码发送部级数据库tbsys_copy表
     * 4.各个省级再从部级copy表中拉取他省机构编码
     */
    @Scheduled(cron = "${gkzx.azbj.zd.pushCron}")
    public void executeDepartChild() {
        boolean flag = true;
        while(flag){
            flag = !executeDepartSave();
        }
    }

    /**
     * 省市区县下拉全国同步(tbsys_code向部级数据库拉取数据)
     * 实现步骤
     * 1.创建定时任务，凌晨1:25开始执行定时任务
     * 2.各个省级系统负责查找其他省-(省市区县)code编码以及机构名称
     * 3.将其他各省数据拉取至本省
     * 4.各个省级再从部级copy表中拉取他省机构编码
     */
    @Scheduled(cron = "${gkzx.azbj.zd.pullCron}")
    public void executePullSystemCode() {
        //拉取tbsys_code表记录
        //定义当天时间戳
        boolean flag = true;
        while(flag){
            flag = !executeSystemCodeDepartUpdate();
        }
    }

    /**
     * 将本省的tbsys_code向司法部同步,只同步一次
     * 实现步骤
     */
    @Scheduled(cron = "0 55 5 * * ?")
    public void syncSfbSystemCode() {
        log.info("=====================向司法部同步SystemCode=========================");
        String localCode = CodeUrlUtils.getLocalCode();
        if (Constants.XzqhCode.HENAN.equals(localCode)) {
            // 连接司法部redis源信息
            try {
                ApplicationContext applicationContext = BizApplication.applicationContext;
                bujiJdbcTemplate = (JdbcTemplate) applicationContext.getBean("bujiJdbcTemplate");
                //查询localCode下的所有省市区县
                List<SystemCode> systemCodes = systemCodeMapper.selectAll();
                if (CollectionUtils.isNotEmpty(systemCodes)) {
                    Date date = new Date();
                    bujiJdbcTemplate.update("delete from tbsys_code");
                    String sqll = " INSERT INTO tbsys_code (id, code_type, code_type_name, code_id, pcode_id, code_name, code_describe, create_time, create_user_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?); ";
                    bujiJdbcTemplate.batchUpdate(sqll, new BatchPreparedStatementSetter() {
                        @Override
                        public void setValues(PreparedStatement preparedStatement, int i) throws SQLException {
                            final SystemCode systemCode = systemCodes.get(i);
                            Timestamp time = new Timestamp(date.getTime());
                            preparedStatement.setInt(1, systemCode.getId());
                            preparedStatement.setString(2, systemCode.getCodeType());
                            preparedStatement.setString(3, systemCode.getCodeTypeName());
                            preparedStatement.setString(4, systemCode.getCodeId());
                            preparedStatement.setString(5, systemCode.getPcodeId());
                            preparedStatement.setString(6, systemCode.getCodeName());
                            preparedStatement.setString(7, systemCode.getCodeDescribe());
                            preparedStatement.setTimestamp(8, time);
                            preparedStatement.setString(9, systemCode.getCreateUserId());
                        }
                        @Override
                        public int getBatchSize() {
                            return systemCodes.size();
                        }
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error(e.getMessage());
            }
        }
    }

    /**
     * 同步机构编码表
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean executeDepartSave() {
        log.info("=====================行政区划开始同步=========================");
        long startTime = System.currentTimeMillis();
        // 连接司法部redis源信息
        try(Jedis jedis = redisConfig.redisPoolFactory().getResource()) {
            //定义当天时间
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
            String localCode = CodeUrlUtils.getLocalCode();
            Date date = new Date();
            try {
                // 删除jedis昨天区划记录
                jedis.hdel("pushTbsysCode",localCode);
                //查询localCode下的所有省市区县
                List<SystemCodeVo> systemCodes = systemCodeMapper.searchByCode(localCode.substring(0,2));
                String systemCodesToString = JsonUtil.toText(systemCodes);
                jedis.hset("pushTbsysCode",localCode,systemCodesToString);
                jedis.hset("pushTbsysSucc",localCode + ":" + simpleDateFormat.format(date),"true");
            } catch(Exception e) {
                log.error("===============行政区划同步异常===============:",e);
                jedis.hset("pushTbsysSucc",localCode + ":" + simpleDateFormat.format(date),"false");
                return false;
            } finally {
                jedis.close();
            }
        }
        long endTime = System.currentTimeMillis();
        log.info("===================行政区划执行完毕---耗时:{},开始时间:{},结束时间:{}", (endTime - startTime) / 1000 / 60, startTime, endTime);
        return true;
    }

    /**
     * 各省同步数据(systemCode)
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean executeSystemCodeDepartUpdate() {
        log.error("=====================抽取字典表=========================");
        long startTime = System.currentTimeMillis();
        try(Jedis jedis = redisConfig.redisPoolFactory().getResource()) {
            //定义当天时间戳
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
            String localCode = CodeUrlUtils.getLocalCode();
            Date date = new Date();
            try {
                Map<String,String> codeMap = jedis.hgetAll("pushTbsysCode");
                if(null != codeMap) {
                    codeMap.forEach((e,v) -> {
                        if(!e.contains(localCode)) {
                            String codeId = e.substring(0,2);
                            systemCodeMapper.deleteTbsysCodeByCode(codeId);
                            List<SystemCode> systemCodes = JsonUtil.toList(v,SystemCode.class);
                            //记录查询的count(1)数,设置systemCodeVo的id值
                            Integer systemCodeMaxId = systemCodeMapper.getTbsysCodeMaxId();
                            int maxId = null == systemCodeMaxId ? 1 : ++systemCodeMaxId;
                            int size = systemCodes.size();
                            for(int i = 0; i < size; i++) {
                                systemCodes.get(i).setId(maxId + i);
                                systemCodes.get(i).insert();
                            }
                        }
                    });
                }
                // 执行成功后将成功标志位存放于redis
                jedis.hset("pullTbsysSucc",localCode + ":" + simpleDateFormat.format(date),"true");
            } catch(DataAccessException e) {
                log.error("===============抽取字典表异常===============:",e);
                jedis.hset("pullTbsysSucc",localCode + ":" + simpleDateFormat.format(date),"false");
                return false;
            } finally {
                jedis.close();
            }
        }
        long endTime = System.currentTimeMillis();
        log.error("===================抽取字典表执行完毕---耗时:{},开始时间:{},结束时间:{}",(endTime - startTime) / 1000 / 60,startTime,endTime);
        return true;
    }


}